﻿Imports Microsoft.VisualBasic

Namespace SimilText
    ' ****
    ' mettere limite di differenza
    ' gestione utenti
    ' stop word
    ' vocabolario da aggingere parole che non ci sono
    ' lettura dati a blocchi 16k?
    ' esempi testi estremi  
    '       (123) (1 2 x x 2  3)  nessuna differenza
    '       (123) (1 2 x 1 2s 3)  non viene considerata la parola simile
    ' multi thread
    ' calcolo automatico delgli errori possibiili

    'test
    'L'esercizio di aziende agricole anche sotto il profilo venatorio, l'allevamento del bestiame, il taglio dei boschi, la produzione e la commercializzazione dei prodotti agricoli, l'attivita' agrituristica, la locazione e la sub locazione immobiliare, e l'attivita' di tipo alberghiera in genere. La societa' potra' inoltre porre in essere qualsiasi operazione mobiliare, immobiliare, commerciale, finanziaria o di credito necessaria per il migliore conseguimento dell' ed assumere, sia direttamente che indirettamente interessenze, quote di partecipazione in altre societa' aventi oggetto analogo, affine o connesso al proprio. Premesso che qualunque attivita' sotto indicata, qualificata dalla legge come finanziaria si intende svolta non nei confronti del pubblico, la societa' potra' compiere ogni operazione mobiliare, immobiliare, commerciale e finanziaria che l'organo amministrativo ritenga utile o necessaria per il conseguimento dell'; potra' assumere ed alienare sia direttamente che indirettamente interessenze o partecipazioni in altre societa' o imprese, costituite o costituende, aventi oggetto analogo, affine o comunque connesso al proprio.

    Public Class CompareText

        Public Property Result As New FindResult
        Public Property Text1 As String
        Public Property Text2 As String
        Public Property UserId As Integer

        Private Property AD As ArchiveData

        Public Sub New(ByVal AD As ArchiveData)

            Me.AD = AD

        End Sub
        Public Function Compare() As FindResult

            Dim tt1 As New TextTools(Me.Text1, Me.AD)
            Dim tt2 As New TextTools(Me.Text2, Me.AD)
            Dim check As New CheckSimilar(Me.AD)


            check.Seq1 = tt1.TextToNumber()
            check.Seq2 = tt2.TextToNumber()
            Me.Result.Matches.Add(check.Check)


            Me.Result.Text1 = Me.Text1
            Me.Result.Text2 = Me.Text2

            Return Me.Result

        End Function

        Public Sub Compare_old()
            Dim diff, ult_par_trovata, par_trovata, par_1, par_2 As Integer
            Dim fa(), fb(), ft() As String
            Dim d(,) As String
            Dim seq As Boolean

            Dim ta As New TextTools(Me.Text1, Me.AD)
            Dim tb As New TextTools(Me.Text2, Me.AD)

            diff = 0
            fa = ta.TextToWord()
            fb = tb.TextToWord()

            par_1 = UBound(fa)
            par_2 = UBound(fb)

            If UBound(fb) > UBound(fa) Then
                ft = fa
                fa = fb
                fb = ft
            End If

            If UBound(fa) = -1 Then
                diff = UBound(fb) + 1
            End If

            If UBound(fb) = -1 Then
                diff = (UBound(fa) + 1)
            End If

            If diff = 0 Then

                ReDim d((UBound(fa) + 1), (UBound(fb) + 1))

                d(0, 0) = 0

                For i = 1 To (UBound(fa) + 1)
                    d(i, 0) = 1
                Next

                For j = 1 To (UBound(fb) + 1)
                    d(0, j) = 1
                Next

                diff = 0
                ult_par_trovata = 0
                For i = 1 To (UBound(fa))
                    seq = False
                    par_trovata = 0
                    For j = 1 To (UBound(fb))
                        If fa(i - 1) = fb(j - 1) Then
                            d(i, j) = 0
                            If d(ult_par_trovata, j - 1) = 0 Then
                                seq = True
                            End If
                            par_trovata = i
                        Else
                            d(i, j) = 1
                        End If
                    Next
                    If par_trovata <> 0 Then ult_par_trovata = par_trovata
                    If Not seq Then
                        diff = diff + 1
                    End If

                Next

            End If

            'max = IIf(par_1 > par_2, par_1, par_2)
            'min = IIf(par_1 < par_2, par_1, par_2)


            'Result.PercDiff1 = diff / par_1 * 100
            'Result.PercDiff2 = diff / par_2 * 100

        End Sub

    End Class

    'Public Class CacheData
    '    Public Data() As Byte
    '    Public BlockId As Integer = -1
    'End Class

    'Public Class CacheDataFile
    '    Public Cache() As CacheData
    '    Public BlockCache() As Integer
    '    Public BlockSize As Integer
    '    Public NumBlock As Integer
    '    Public File As IO.BinaryReader
    '    Public FileLength As Integer
    '    Public CurrBlock As Integer
    '    Private LastBlockCreate, OldBlockCreate, NumBlockAssigned As Integer

    '    Public Sub New(ByVal BlockSize As Integer, ByVal NumBlock As Integer, ByRef File As IO.BinaryReader, ByVal FileLength As Integer)
    '        ReDim Me.Cache(NumBlock)

    '        Me.BlockSize = BlockSize
    '        Me.NumBlock = NumBlock
    '        Me.File = File
    '        Me.FileLength = FileLength
    '        Me.LastBlockCreate = -1
    '        Me.OldBlockCreate = -1
    '        Me.NumBlockAssigned = 0

    '        ReDim BlockCache(Int(FileLength / BlockSize) + 1)
    '        For ct = 0 To BlockCache.Length - 1
    '            BlockCache(ct) = -1
    '        Next

    '        For ct = 0 To NumBlock - 1
    '            Me.Cache(ct) = New CacheData
    '        Next

    '    End Sub

    '    Public Function GetData(ByVal Index As Integer, ByRef Buffer() As Byte) As Integer
    '        Dim DataLen As Integer
    '        Dim Res As Integer
    '        Dim CurrBlockCache As Integer

    '        CurrBlock = Int(Index / BlockSize)


    '        If BlockCache(CurrBlock) = -1 Then

    '            ' verifica quato deve leggere dal file
    '            DataLen = BlockSize
    '            If FileLength - (CurrBlock * BlockSize) < BlockSize Then
    '                DataLen = FileLength - (CurrBlock * BlockSize)
    '            End If

    '            If NumBlockAssigned < NumBlock Then
    '                LastBlockCreate += 1
    '                NumBlockAssigned += 1
    '                CurrBlockCache = LastBlockCreate
    '            Else
    '                OldBlockCreate += 1
    '                If OldBlockCreate >= NumBlock Then
    '                    OldBlockCreate = 0
    '                End If
    '                CurrBlockCache = OldBlockCreate
    '            End If

    '            ReDim Me.Cache(CurrBlockCache).Data(BlockSize)
    '            File.BaseStream.Seek(CurrBlock * BlockSize, IO.SeekOrigin.Begin)
    '            File.Read(Cache(CurrBlockCache).Data, 0, DataLen)
    '            Me.Cache(CurrBlockCache).BlockId = CurrBlock
    '            BlockCache(CurrBlock) = CurrBlockCache
    '            Res = 1

    '        Else
    '            Res = 0
    '            CurrBlockCache = BlockCache(CurrBlock)
    '        End If

    '        Buffer = Cache(CurrBlockCache).Data

    '        Return Res

    '    End Function

    'End Class

    'Public Class FindSimilar

    '    Public Enum FindSimilarState
    '        [Stop] = 0
    '        Active = 1
    '        Finish = 2
    '    End Enum


    '    Private _PercMaxDiff As Double = 0
    '    Public Property PercMaxDiff As Double
    '        Get
    '            Return _PercMaxDiff
    '        End Get
    '        Set(ByVal value As Double)
    '            _PercMaxDiff = value
    '            PercToNumDiff()
    '        End Set
    '    End Property
    '    Private _AutoPercMaxDiff As Boolean
    '    Public Property AutoPercMaxDiff As Boolean
    '        Get
    '            Return _AutoPercMaxDiff
    '        End Get
    '        Set(ByVal value As Boolean)
    '            _AutoPercMaxDiff = value
    '            PercToNumDiff()
    '        End Set
    '    End Property
    '    Private _SeqToFind() As UInteger
    '    Public Property SeqToFind() As UInteger()
    '        Get
    '            Return _SeqToFind
    '        End Get
    '        Set(ByVal value() As UInteger)
    '            _SeqToFind = value
    '            PercToNumDiff()
    '        End Set
    '    End Property

    '    Public UseDictionary As Boolean
    '    Public TI As Data
    '    Public Buffer() As Byte
    '    Public NumBlock As Integer
    '    Public Results As List(Of SimilarResult)
    '    Public State As FindSimilarState = FindSimilarState.Stop
    '    Public Filters As New List(Of FindSimilarText.FilterText)

    '    Private NumMaxDiff As Integer


    '    Public Sub New(ByVal TextInit As Data)

    '        Me.TI = TextInit

    '    End Sub

    '    Private Delegate Sub FindDelegate()
    '    Private FindDel As New FindDelegate(AddressOf Find)

    '    Private Sub PercToNumDiff()

    '        If Me.SeqToFind IsNot Nothing Then

    '            Me.NumMaxDiff = Math.Round(SeqToFind.Length * _PercMaxDiff) + 1

    '            If Me.AutoPercMaxDiff Then
    '                Dim TempNumMaxDiff As Integer
    '                TempNumMaxDiff = SeqToFind.Length / 2
    '                If TempNumMaxDiff > 300 Then TempNumMaxDiff = 300
    '                If SeqToFind.Length - TempNumMaxDiff < 30 Then TempNumMaxDiff = SeqToFind.Length - 30
    '                If TempNumMaxDiff < 0 Then TempNumMaxDiff = 0
    '                TempNumMaxDiff = TempNumMaxDiff * 100

    '                If TempNumMaxDiff < Me.NumMaxDiff Then
    '                    Me.NumMaxDiff = TempNumMaxDiff
    '                    Me._PercMaxDiff = Me.NumMaxDiff / SeqToFind.Length
    '                End If

    '            Else
    '                Me.NumMaxDiff = Math.Round(SeqToFind.Length * _PercMaxDiff) + 1
    '            End If
    '        End If

    '    End Sub

    '    Public Sub FindAsync()

    '        Me.State = FindSimilarState.Active

    '        FindDel.BeginInvoke(Nothing, Nothing)

    '    End Sub

    '    Public Sub Find()
    '        Dim check As New CheckSimilar(Me.TI)
    '        Dim i, j As UInteger
    '        Dim Currtext As TextElement
    '        Dim EndPos As UInteger
    '        Dim r As SimilarResult
    '        Dim CurrPosIndex As Integer

    '        Results = New List(Of SimilarResult)

    '        'assegna prop alla check
    '        check.UseDictionary = Me.UseDictionary
    '        check.NumMaxDiff = Me.NumMaxDiff

    '        ' trasporma il testi pivot in numeri
    '        check.Seq1 = Me.SeqToFind

    '        If Me.Filters.Count > 0 Then
    '            '**** gestione filtri
    '            'trova la posizione del primo indice
    '            CurrPosIndex = -1
    '            i = Me.Filters(0).FindNextPos(CurrPosIndex, Me.NumBlock)
    '            EndPos = UInteger.MaxValue

    '        Else
    '            i = Me.NumBlock * TI.BlockSize
    '            EndPos = i + Buffer.Length - 1
    '        End If

    '        'cicla della lettura del file
    '        Do Until i >= EndPos

    '            'calcola offset del blocco
    '            j = i Mod TI.BlockSize
    '            ' legge il testo
    '            Currtext = New TextElement(Buffer, j)
    '            If Currtext.Id <> UInt32.MaxValue Then

    '                'imposta la sequenza da verificare
    '                check.Seq2 = Currtext.DataText
    '                'confronto pivot con testo
    '                r = check.Check()

    '                ' se la differenza è minore di quella impostasta aggiunggi l'elemento ai risulati
    '                If r.PercDiff <= Me.PercMaxDiff Then
    '                    r.Id = Currtext.Id
    '                    r.Attributes(0) = Currtext.Attributes(0)
    '                    r.Attributes(1) = Currtext.Attributes(1)
    '                    Me.Results.Add(r)
    '                End If

    '                If Me.Filters.Count > 0 Then
    '                    '-----------------------------------
    '                    ' gestione filtri
    '                    'se ci sono de filtri va al testo dopo
    '                    i = Currtext.NextForAttributeRef(Me.Filters(0).Index.IndexType)
    '                    ' se non esiste il testo succesivo vai alla key sucessiva me dello stesso blocco
    '                    If i = UInteger.MaxValue Then
    '                        'vai al puntatore della key sucessiva dello stesso blocca
    '                        i = Me.Filters(0).FindNextPos(CurrPosIndex, Me.NumBlock)
    '                    End If
    '                Else
    '                    ' se la ricerca fullscan vai a quello dopo
    '                    i = NumBlock * TI.BlockSize + j
    '                End If

    '            Else
    '                'se ID = 0 vuol dire che non esiste e quindi ha finito il blocco
    '                i = EndPos
    '            End If

    '        Loop

    '        Me.State = FindSimilarState.Finish
    '        'Return Me.Result

    '    End Sub

    'End Class

    Public Class FindSimilarText

        ' to do 
        ' mettere un sistema di cache per blocchi, rivedere la ReadBlockFile

        'Dim NumThread As Integer = 4

        Public Property Result As FindResult
        Public Property Text As String
        Public Property RankMin As Double
        'Public Property UseDictionary As Boolean

        Private AD As ArchiveData
        Private CurrNumBlock As Integer
        Private fr As IO.BinaryReader
        Private Folder As String
        Private Filters As New List(Of FilterText)
        'Private Indexes As New List(Of ArchiveIndex)

        Public Sub New(ByVal AD As ArchiveData)
            Me.AD = AD
            Me.RankMin = 0
            Me.Folder = AD.IndexesPath

            'apro il file
            fr = New IO.BinaryReader(New IO.FileStream(Folder & AD.ArchiveFile, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read))

        End Sub

        Public Sub AddFilter(ByVal Min As Integer, ByVal Max As Integer, ByVal IndexType As Integer)
            Dim f As New FilterText

            f.ValueMin = Min
            f.ValueMax = Max
            f.IndexType = IndexType

            Me.Filters.Add(f)

        End Sub

        'Public Sub Filter(ByVal IndexType As ArchiveIndexType, ByVal Min As Integer, ByVal Max As Integer)
        '    Dim f As FilterText

        '    If Not IndexFilter.ContainsKey(IndexType) Then
        '        f = New FilterText
        '        f.ValueMin = Min
        '        f.ValueMax = Max
        '        f.Index = Index(IndexType)
        '        f.NumRecCalc = 1 / f.Index.Count * (f.Index.FindKey(f.ValueMax) - f.Index.FindKey(f.ValueMin))
        '        Me.Filters.Add(f)

        '        IndexFilter.Add(IndexType, Me.Filters.Count - 1)
        '    Else
        '        f = Me.Filters(IndexFilter(IndexType))
        '    End If

        '    f.ValueMin = Min
        '    f.ValueMax = Max

        'End Sub

        Public Sub ResetFilters()

            Me.Filters.Clear()


        End Sub


        'Public Function Find_old() As SimilarResults
        '    Dim check As New CheckSimilar
        '    Dim r As SimilarResult
        '    Dim t As ULong
        '    Dim i, j, DataLen As Integer
        '    Dim fi As IO.FileInfo
        '    Dim utext As TextUnit


        '    check.PercMaxDiff = Me.PercMaxDiff
        '    ' trasporma il testi pivot in numeri
        '    check.Seq1 = New TextTools(Me.text, Me.TI).TextToNumberDic


        '    fi = New IO.FileInfo(Folder & TI.ArchiveFile)
        '    'Dim fr As IO.FileStream = New IO.FileStream(Folder & TI.ArchiveFile, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
        '    Dim fr As New IO.BinaryReader(New IO.FileStream(Folder & TI.ArchiveFile, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read))


        '    'fr.Position 
        '    'fr.Seek(0, IO.SeekOrigin.Begin)

        '    ' se ci sono dei filtri bisogna partire dal primo

        '    Dim CacheData() As dd
        '    ReDim CacheData(Math.Round(fi.Length / TI.BlockSize) + 1)
        '    Dim NumBlock As Integer

        '    i = 0
        '    t = Now.Ticks

        '    'cicla della lettura del file
        '    Do Until i >= fi.Length

        '        NumBlock = Int(i / TI.BlockSize)

        '        DataLen = TI.BlockSize
        '        If fi.Length - i < TI.BlockSize Then
        '            DataLen = fi.Length - i
        '        End If

        '        If CacheData(NumBlock).d Is Nothing Then
        '            ReDim CacheData(NumBlock).d(TI.BlockSize)
        '            fr.Read(CacheData(NumBlock).d, 0, DataLen)
        '            'fr.Read(DataTemp, 0, DataLen)
        '        Else

        '        End If

        '        i += DataLen
        '        j = 0
        '        'cicla tutti i testi
        '        Do Until j >= DataLen

        '            ' carico il testo
        '            'utext = New TextUnit(DataTemp, j)
        '            utext = New TextUnit(CacheData(NumBlock).d, j)
        '            If utext.Id = 0 Then
        '                Exit Do
        '            End If

        '            'confronto pivot con testo
        '            check.Seq2 = utext.DataText
        '            r = check.Check()

        '            If r.PercDiff1 < Me.PercMaxDiff Then
        '                r.Id = utext.Id
        '                r.Attribute1 = utext.Attribute1
        '                r.Attribute2 = utext.Attribute2
        '                Me.Result.Results.Add(r)
        '            End If

        '            ' se ci sono i filtri a seconda del filtro vai a quello sucessivo

        '        Loop
        '    Loop

        '    fr.Close()

        '    Me.Result.ExecTime = (Now.Ticks - t) / 10000000
        '    Me.Result.Results = Me.Result.Results.OrderByDescending(Function(o) o.PercDiff1).ToList
        '    Me.Result.Text1 = Me.text
        '    Me.Result.Text2 = ""

        '    Return Me.Result

        'End Function

        'Public Sub ottfiltri()
        '    Dim IndexAttr As ArchiveIndex
        '    Dim IndexDate As ArchiveIndex
        '    Dim NumRecPerKeyAttr, NumRecPerKeyDate As Integer

        '    Dim TotTextElement As Integer = 1000
        '    Dim NumTextElementAttr, NumTextElementDate As Integer

        '    If Me.FilterAttr Then
        '        IndexAttr = New ArchiveIndex(TI.ArchiveData & TI.IndexFileAttr)
        '        IndexAttr.SortedIndex()

        '        'NumRecPerKeyAttr = TotTextElement / IndexAttr.Count
        '        NumTextElementAttr = TotTextElement / IndexAttr.Count * (IndexAttr.findkey(Me.FilterAttrMax) - IndexAttr.findkey(Me.FilterAttrMin))
        '        'CurrPosIndex = IndexAttr.findkey(Me.FilterAttrMin)
        '        'i = IndexAttr.SortIndex(CurrPosIndex).Value.FirstTextRef
        '    End If

        '    If Me.FilterDate Then
        '        IndexDate = New ArchiveIndex(TI.ArchiveData & TI.IndexFileAttr)
        '        IndexDate.SortedIndex()
        '        'CurrPosIndex = IndexAttr.findkey(Me.FilterAttrMin)
        '        'i = IndexAttr.SortIndex(CurrPosIndex).Value.FirstTextRef
        '    End If

        'End Sub



        'Public Function Findcallb(ByVal ar As System.IAsyncResult)
        '    Dim t As Integer = ar.AsyncState

        '    elenco(t, 0) += 1

        '    del(t).BeginInvoke(elenco(t, elenco(t, 0)), cb, t)


        'End Function

        ' inizilizza l'oggetto cache **** definire la quantità di memoria da usare per una ricerca

        'Public Sub Open()
        '    'apro il file
        '    fr = New IO.BinaryReader(New IO.FileStream(Folder & AD.ArchiveFile, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read))


        'End Sub

        Public Sub Close()
            'chiudo indici
            'For ct As Integer = 0 To Me.Filters.Count - 1
            '    Me.Filters(ct).Index.Close()
            'Next

            'chiudo archivio
            fr.Close()
        End Sub

        Public Function Find() As FindResult
            Dim t As ULong
            Dim TotBlock As Integer

            Me.Result = New FindResult


            ' sequenza pivot
            Dim SeqToFind = New TextTools(Me.Text, Me.AD).TextToNumber

            t = Now.Ticks
            TotBlock = Int(fr.BaseStream.Length / Me.AD.BlockSize) + 1

            ' IMPORTANTE ordina i filtri in base a quello che deve essere filtrato per primo, cioè di quello che si ritiene che abbiamo meno record da analizzare
            'Me.Filters = Me.Filters.OrderByDescending(Function(o) o.NumRecCalc).ToList

            '----------------------------------------------
            ' inizio elaborazione
            CurrNumBlock = 0

            Dim Threads As New Utils.Threading.ThreadsManage(Me.AD.ThreadNumber)
            Do

                Dim check As New CheckSimilar(Me.AD)

                'assegna prop alla check
                check.RankMin = Me.RankMin
                check.Seq1 = SeqToFind ' New TextTools(Me.Text, Me.TI).TextToNumberDic

                Threads.Start(AddressOf Me.FindIntoBlock, New With {
                    .check = check, .NumBlock = CurrNumBlock
                })

                Me.CurrNumBlock += 1
            Loop Until Me.CurrNumBlock >= TotBlock

            Threads.WaitEnd()

            '----------------------------------------------
            'fine elaborazione


            Const NumViewResults As Integer = 1000

            Me.Result.Matches = Me.Result.Matches.OrderByDescending(Function(o) o.Accuracy).ToList
            Me.Result.CountResults = Me.Result.Matches.Count
            If Me.Result.CountResults > NumViewResults Then
                '**** forse conviene prendere i primi con un take
                'Me.Result.Matches.RemoveRange(NumViewResults, Me.Result.CountResults - NumViewResults)
            End If
            Me.Result.ExecTime = (Now.Ticks - t) / 10000000

            Me.Result.PercMaxDiff = Me.RankMin
            'Me.Result.UseDictionary = Me.UseDictionary
            Me.Result.Text1 = Me.Text
            Me.Result.Text2 = ""

            Return Me.Result
        End Function
        Private Sub ReadBlockFile(ByVal f As IO.BinaryReader, ByVal NBlock As Integer, ByRef b() As Byte)

            'leggo e gli passo il buffer sul quale deve lavorare
            Dim LenFile As Integer = f.BaseStream.Length
            Dim DataLen As Integer = AD.BlockSize
            'se il file rimante è + piccolo del blocco lo taglio
            If LenFile - (NBlock * AD.BlockSize) < AD.BlockSize Then
                DataLen = LenFile - (NBlock * AD.BlockSize)
            End If

            ReDim b(DataLen)

            SyncLock f
                f.BaseStream.Seek(NBlock * AD.BlockSize, IO.SeekOrigin.Begin)
                f.Read(b, 0, DataLen)
            End SyncLock

        End Sub

        'Private Sub PercToNumDiff()

        '    If Me.SeqToFind IsNot Nothing Then

        '        Me.NumMaxDiff = Math.Round(SeqToFind.Length * _PercMaxDiff) + 1

        '        If Me.AutoPercMaxDiff Then
        '            Dim TempNumMaxDiff As Integer
        '            TempNumMaxDiff = SeqToFind.Length / 2
        '            If TempNumMaxDiff > 300 Then TempNumMaxDiff = 300
        '            If SeqToFind.Length - TempNumMaxDiff < 30 Then TempNumMaxDiff = SeqToFind.Length - 30
        '            If TempNumMaxDiff < 0 Then TempNumMaxDiff = 0
        '            TempNumMaxDiff = TempNumMaxDiff * 100

        '            If TempNumMaxDiff < Me.NumMaxDiff Then
        '                Me.NumMaxDiff = TempNumMaxDiff
        '                Me._PercMaxDiff = Me.NumMaxDiff / SeqToFind.Length
        '            End If

        '        Else
        '            Me.NumMaxDiff = Math.Round(SeqToFind.Length * _PercMaxDiff) + 1
        '        End If
        '    End If

        'End Sub


        Private Sub FindIntoBlock(d As Object)
            Dim check As CheckSimilar = d.check
            Dim NumBlock As Integer = d.NumBlock

            Dim Res As New List(Of MatchResult)
            Dim i, j As UInteger
            Dim Currtext As TextElement
            Dim EndPos As UInteger
            Dim r As MatchResult
            Dim CurrPosIndex As Integer
            Dim Buffer() As Byte = {}

            Dim Index As ArchiveIndex = Nothing
            Dim Filter As FilterText = Nothing


            Dim WordCluster1 As New Dictionary(Of UInt32, Integer)
            Dim HashTagCluster1 As New Dictionary(Of UInt32, Integer)
            Dim HashTagCluster2 As New Dictionary(Of String, Integer)
            Dim HashTagCluster3 As New Dictionary(Of String, Integer)

            'leggo e gli passo il buffer sul quale deve lavorare
            'SyncLock fr
            ReadBlockFile(fr, NumBlock, Buffer)
            'End SyncLock

            If Me.Filters.Count > 0 Then
                '**** gestione filtri
                'trova la posizione del primo indice
                Filter = Me.Filters(0)
                Index = New ArchiveIndex(AD, Filter.IndexType, NumBlock)

                CurrPosIndex = -1
                i = Index.FindNextPos(CurrPosIndex, Filter.ValueMin, Filter.ValueMax)
                EndPos = UInteger.MaxValue

            Else
                i = NumBlock * AD.BlockSize
                EndPos = i + Buffer.Length - 1
            End If

            'cicla della lettura del file
            Do Until i >= EndPos

                'calcola offset del blocco
                j = i Mod AD.BlockSize
                ' legge il testo
                Currtext = New TextElement(Me.AD)
                Currtext.Load(Buffer, j)
                If Currtext.Id <> UInt32.MaxValue Then

                    'imposta la sequenza da verificare
                    check.Seq2 = Currtext.DataText
                    'confronto pivot con testo
                    r = check.Check()

                    ' se la differenza è minore di quella impostasta aggiunggi l'elemento ai risulati
                    If r.Accuracy >= Me.RankMin Then
                        r.Id = Currtext.Id
                        r.Attributes = Currtext.Attributes

                        'r.Seq = check.Seq2
                        '------------------------------------------------------------
                        ' trovo le parole + usate
                        Dim TmpDic As New Dictionary(Of UInt32, Integer)

                        For ct = 0 To check.Seq2.Length - 1
                            If AD.Dictionary.WordsList(check.Seq2(ct)).IsHashtag Then
                                TmpDic = HashTagCluster1
                            Else
                                TmpDic = WordCluster1
                            End If

                            If TmpDic.ContainsKey(check.Seq2(ct)) Then
                                TmpDic(check.Seq2(ct)) += 1
                            Else
                                TmpDic.Add(check.Seq2(ct), 1)
                            End If

                        Next

                        '------------------------------------------------------------
                        ' trovo i cluster 2
                        Dim HashtagPost = check.Seq2.Where(Function(o) AD.Dictionary.WordsList(o).IsHashtag).Distinct.OrderBy(Function(o) o).ToArray
                        For ct2 = 0 To HashtagPost.Length - 2
                            For ct3 = ct2 + 1 To HashtagPost.Length - 1
                                Dim k = String.Concat(HashtagPost(ct2), "_", HashtagPost(ct3))
                                'IncKey({ii(ct2 - 1), ii(ct3 - 1)})
                                If HashTagCluster2.ContainsKey(k) Then
                                    HashTagCluster2(k) += 1
                                Else
                                    HashTagCluster2.Add(k, 1)
                                End If
                            Next
                        Next

                        ''------------------------------------------------------------
                        ' trovo i cluster 3
                        For ct1 = 0 To HashtagPost.Length - 3
                            For ct2 = ct1 + 1 To HashtagPost.Length - 2
                                For ct3 = ct2 + 1 To HashtagPost.Length - 1
                                    'IncKey({i(ct1 - 1), i(ct2 - 1), i(ct3 - 1)})
                                    Dim k = String.Concat(HashtagPost(ct1), "_", HashtagPost(ct2), "_", HashtagPost(ct3))
                                    'IncKey({ii(ct2 - 1), ii(ct3 - 1)})
                                    If HashTagCluster3.ContainsKey(k) Then
                                        HashTagCluster3(k) += 1
                                    Else
                                        HashTagCluster3.Add(k, 1)
                                    End If
                                Next
                            Next
                        Next


                        '-----------------------
                        Res.Add(r)

                    End If

                    If Me.Filters.Count > 0 Then
                        '-----------------------------------
                        ' gestione filtri
                        'se ci sono de filtri va al testo dopo
                        i = Currtext.NextForAttributeRef(Filter.IndexType)
                        ' se non esiste il testo succesivo vai alla key sucessiva me dello stesso blocco
                        If i = UInteger.MaxValue Then
                            'vai al puntatore della key sucessiva dello stesso blocca
                            i = Index.FindNextPos(CurrPosIndex, Filter.ValueMin, Filter.ValueMax)
                        End If
                    Else
                        ' se la ricerca fullscan vai a quello dopo
                        i = NumBlock * AD.BlockSize + j
                    End If

                Else
                    'se ID = 0 vuol dire che non esiste e quindi ha finito il blocco
                    i = EndPos
                End If
                'Currtext = Nothing
            Loop

            'aggiungi tutti i match del blocco
            SyncLock Me.Result.Matches
                Me.Result.Matches.AddRange(Res)

                For Each t In WordCluster1
                    If Me.Result.WordCluster1.ContainsKey(t.Key) Then
                        Me.Result.WordCluster1(t.Key) += t.Value
                    Else
                        Me.Result.WordCluster1.Add(t.Key, t.Value)
                    End If

                Next

                For Each t In HashTagCluster1
                    If Me.Result.HashTagCluster1.ContainsKey(t.Key) Then
                        Me.Result.HashTagCluster1(t.Key) += t.Value
                    Else
                        Me.Result.HashTagCluster1.Add(t.Key, t.Value)
                    End If

                Next

                For Each t In HashTagCluster2
                    If Me.Result.HashTagCluster2.ContainsKey(t.Key) Then
                        Me.Result.HashTagCluster2(t.Key) += t.Value
                    Else
                        Me.Result.HashTagCluster2.Add(t.Key, t.Value)
                    End If
                Next

                For Each t In HashTagCluster3
                    If Me.Result.HashTagCluster3.ContainsKey(t.Key) Then
                        Me.Result.HashTagCluster3(t.Key) += t.Value
                    Else
                        Me.Result.HashTagCluster3.Add(t.Key, t.Value)
                    End If
                Next


            End SyncLock

            'Buffer = Nothing

        End Sub

        Public Class FilterText
            Public Property ValueMin As Integer
            Public Property ValueMax As Integer
            'Public Property NumRecCalc As Integer
            'Public Property Index As ArchiveIndex
            Public Property IndexType As Integer


        End Class

        'Public Sub Findasy(ByVal inizio As Integer, ByVal fine As Integer)
        '    Dim c As CacheDataFile
        '    Dim datatempp() As Byte
        '    Dim check As New CheckSimilar(Me.TI)
        '    Dim i, j As UInteger
        '    Dim Currtext As TextElement
        '    Dim LenFile As UInteger
        '    Dim r As SimilarResult
        '    Dim blocco As Integer = inizio / Me.TI.BlockSize

        '    'assegna la percentuale massima di differenza
        '    check.PercMaxDiff = Me.PercMaxDiff
        '    check.AutoPercMaxDiff = Me.AutoPercMaxDiff
        '    check.UseDictionary = Me.UseDictionary

        '    ' trasporma il testi pivot in numeri
        '    check.Seq1 = New TextTools(Me.Text, Me.TI).TextToNumberDic

        '    If Me.AutoPercMaxDiff Then Me.PercMaxDiff = check.PercMaxDiff

        '    ' inizilizza l'oggetto cache **** definire la quantità di memoria da usare per una ricerca
        '    c = New CacheDataFile(TI.BlockSize, 1, frasync, frasync.BaseStream.Length)

        '    i = inizio
        '    LenFile = fine

        '    'cicla della lettura del file
        '    Do Until i >= LenFile

        '        ' prende i dati usando la cache
        '        c.GetData(i, datatempp)
        '        'calcola offset del blocco
        '        j = i Mod c.BlockSize
        '        ' legge il testo
        '        Currtext = New TextElement(datatempp, j)
        '        If Currtext.Id <> UInt32.MaxValue Then

        '            'imposta la sequenza da verificare
        '            check.Seq2 = Currtext.DataText
        '            'confronto pivot con testo
        '            r = check.Check()


        '            'r = check.CheckWithDictionary()

        '            ' se la differenza è minore di quella impostasta aggiunggi l'elemento ai risulati
        '            If r.PercDiff <= Me.PercMaxDiff Then
        '                r.Id = Currtext.Id
        '                r.Attributes(0) = Currtext.Attributes(0)
        '                r.Attributes(1) = Currtext.Attributes(1)
        '                Results(blocco).Add(r)
        '            End If

        '            If Me.Filters.Count > 0 Then

        '            Else
        '                ' se la ricerca fullscan vai a quello dopo

        '                i = c.CurrBlock * c.BlockSize + j
        '            End If

        '        Else
        '            'se ID = 0 vuol dire che non esiste e va al blocco successivo
        '            i = c.BlockSize * (c.CurrBlock + 1)
        '        End If

        '        ' se ci sono i filtri a seconda del filtro vai a quello sucessivo

        '    Loop

        '    dafare += 1

        '    'Return Me.Result

        'End Sub



        'Public Function Find() As SimilarResults

        '    Dim check As New CheckSimilar(Me.TI)
        '    Dim r As SimilarResult
        '    Dim t As ULong
        '    Dim i, j As UInteger
        '    Dim Currtext As TextElement
        '    Dim LenFile As UInteger

        '    Dim CurrPosIndex, CurrPosIndexBlock As Integer

        '    t = Now.Ticks

        '    'assegna la percentuale massima di differenza
        '    check.PercMaxDiff = Me.PercMaxDiff
        '    check.AutoPercMaxDiff = Me.AutoPercMaxDiff
        '    check.UseDictionary = Me.UseDictionary

        '    ' trasporma il testi pivot in numeri
        '    check.Seq1 = New TextTools(Me.Text, Me.TI).TextToNumberDic

        '    If Me.AutoPercMaxDiff Then Me.PercMaxDiff = check.PercMaxDiff

        '    Dim fr As New IO.BinaryReader(New IO.FileStream(Folder & TI.ArchiveFile, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read))
        '    LenFile = fr.BaseStream.Length

        '    ' inizilizza l'oggetto cache **** definire la quantità di memoria da usare per una ricerca
        '    Dim c As New CacheDataFile(TI.BlockSize, 30, fr, LenFile)

        '    ' gestione filtri
        '    Me.Filters = Me.Filters.OrderByDescending(Function(o) o.NumRecCalc).ToList
        '    If Me.Filters.Count > 0 Then
        '        'trova la posizione del primo indice
        '        CurrPosIndex = Me.Filters(0).Index.FindKey(Me.Filters(0).ValueMin)
        '        CurrPosIndexBlock = 0
        '        i = Me.Filters(0).Index.SortIndex(CurrPosIndex).Value(CurrPosIndexBlock).FirstTextRef
        '    Else
        '        i = 0
        '    End If

        '    'cicla della lettura del file
        '    Do Until i >= LenFile

        '        ' prende i dati usando la cache
        '        c.GetData(i, DataTemp)
        '        'calcola offset del blocco
        '        j = i Mod c.BlockSize
        '        ' legge il testo
        '        Currtext = New TextElement(DataTemp, j)
        '        If Currtext.Id <> UInt32.MaxValue Then

        '            'imposta la sequenza da verificare
        '            check.Seq2 = Currtext.DataText
        '            'confronto pivot con testo
        '            r = check.Check()
        '            'r = check.CheckWithDictionary()

        '            ' se la differenza è minore di quella impostasta aggiunggi l'elemento ai risulati
        '            If r.PercDiff <= Me.PercMaxDiff Then
        '                r.Id = Currtext.Id
        '                r.Attributes(0) = Currtext.Attributes(0)
        '                r.Attributes(1) = Currtext.Attributes(1)
        '                Me.Result.Results.Add(r)
        '            End If

        '            If Me.Filters.Count > 0 Then
        '                'se ci sono de filtri va al testo dopo
        '                i = Currtext.NextForAttributeRef(Me.Filters(0).Index.IndexType)
        '                ' se non esiste il testo succesivo vai alla key o al blocco sucessiva
        '                If i = UInteger.MaxValue Then
        '                    'verifico se sono all'ultimo blobbo della key corrente
        '                    If Me.Filters(0).Index.SortIndex(CurrPosIndex).Value.Count - 1 > CurrPosIndexBlock Then
        '                        'vado al blocco sucessimo
        '                        CurrPosIndexBlock += 1
        '                        i = Me.Filters(0).Index.SortIndex(CurrPosIndex).Value(CurrPosIndexBlock).FirstTextRef
        '                    Else
        '                        'verifico se dopo esiste una key sucessiva
        '                        If CurrPosIndex < Me.Filters(0).Index.SortIndex.Count - 1 Then
        '                            ' va alla posizine della key sucessiva al blocco 0
        '                            CurrPosIndex += 1
        '                            CurrPosIndexBlock = 0
        '                            'verifica se la key sucessiva è dentro al filtro massimo
        '                            If Me.Filters(0).Index.SortIndex(CurrPosIndex).Key <= Me.Filters(0).ValueMax Then
        '                                'posizione del testo della key sucessiva e al blocco 0
        '                                i = Me.Filters(0).Index.SortIndex(CurrPosIndex).Value(CurrPosIndexBlock).FirstTextRef
        '                            Else
        '                                i = LenFile
        '                            End If
        '                        Else
        '                            i = LenFile
        '                        End If

        '                    End If

        '                End If
        '            Else
        '                ' se la ricerca fullscan vai a quello dopo
        '                i = c.CurrBlock * c.BlockSize + j
        '            End If

        '        Else
        '            'se ID = 0 vuol dire che non esiste e va al blocco successivo
        '            i = c.BlockSize * (c.CurrBlock + 1)
        '        End If

        '        ' se ci sono i filtri a seconda del filtro vai a quello sucessivo

        '    Loop

        '    fr.Close()

        '    Const NumViewResults As Integer = 100

        '    Me.Result.Results = Me.Result.Results.OrderBy(Function(o) o.PercDiff).ToList
        '    Me.Result.CountResults = Me.Result.Results.Count
        '    If Me.Result.CountResults > NumViewResults Then
        '        Me.Result.Results.RemoveRange(NumViewResults, Me.Result.CountResults - NumViewResults)
        '    End If
        '    Me.Result.ExecTime = (Now.Ticks - t) / 10000000
        '    Me.Result.PercMaxDiff = Me.PercMaxDiff
        '    Me.Result.UseDictionary = Me.UseDictionary
        '    Me.Result.Text1 = Me.Text
        '    Me.Result.Text2 = ""

        '    Return Me.Result

        'End Function



        'Delegate Sub FindasyDelegate()

        'Public Function Findtt() As SimilarResults
        '    Dim geo(20) As CheckSimilar
        '    Dim del(20) As FindasyDelegate
        '    Dim numt As Integer = 10
        '    Dim trovatolibero As Boolean

        '    For ct As Integer = 0 To geo.Length - 1
        '        geo(ct) = New CheckSimilar(Me.TI)
        '        geo(ct).PercMaxDiff = Me.PercMaxDiff
        '        geo(ct).AutoPercMaxDiff = Me.AutoPercMaxDiff
        '        geo(ct).UseDictionary = Me.UseDictionary
        '        geo(ct).Seq1 = New TextTools(Me.Text, Me.TI).TextToNumberDic
        '        del(ct) = New FindasyDelegate(AddressOf geo(ct).Check)

        '        If Me.AutoPercMaxDiff Then Me.PercMaxDiff = geo(ct).PercMaxDiff

        '    Next


        '    ' trasporma il testi pivot in numeri

        '    '------------------------------------------------------------------

        '    Dim r As SimilarResult
        '    Dim t As ULong
        '    Dim i, j As UInteger
        '    Dim Currtext As TextElement
        '    Dim LenFile As UInteger

        '    'Dim IndexAttr As ArchiveIndex
        '    Dim CurrPosIndex, CurrPosIndexBlock As Integer

        '    t = Now.Ticks


        '    Dim fr As New IO.BinaryReader(New IO.FileStream(Folder & TI.ArchiveFile, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read))
        '    LenFile = fr.BaseStream.Length

        '    ' inizilizza l'oggetto cache **** definire la quantità di memoria da usare per una ricerca
        '    Dim c As New CacheDataFile(TI.BlockSize, 30, fr, LenFile)

        '    ' gestione filtri
        '    Me.Filters = Me.Filters.OrderByDescending(Function(o) o.NumRecCalc).ToList
        '    If Me.Filters.Count > 0 Then
        '        'trova la posizione del primo indice
        '        CurrPosIndex = Me.Filters(0).Index.FindKey(Me.Filters(0).ValueMin)
        '        CurrPosIndexBlock = 0
        '        i = Me.Filters(0).Index.SortIndex(CurrPosIndex).Value(CurrPosIndexBlock).FirstTextRef
        '    Else
        '        i = 0
        '    End If

        '    'cicla della lettura del file
        '    Do Until i >= LenFile

        '        ' prende i dati usando la cache
        '        c.GetData(i, DataTemp)
        '        'calcola offset del blocco
        '        j = i Mod c.BlockSize
        '        ' legge il testo
        '        Currtext = New TextElement(DataTemp, j)
        '        If Currtext.Id <> UInt32.MaxValue Then

        '            'imposta la sequenza da verificare
        '            'confronto pivot con testo
        '            'r = check.Check()
        '            'r = check.CheckWithDictionary()

        '            '--------------------------------------------------------

        '            trovatolibero = False
        '            Do
        '                For ct As Integer = 0 To numt - 1

        '                    If geo(ct).stato <> 1 Then

        '                        ' le la differenza è mi nore di quella impostasta aggiunggi l'elemento hai risulati
        '                        If geo(ct).stato = 2 Then
        '                            geo(ct).stato = 1
        '                            r = geo(ct).Result
        '                            If r.PercDiff <= Me.PercMaxDiff Then
        '                                '**** SBLAGLIATO prende il corrente invede deve prendere quello elaborato
        '                                r.Id = Currtext.Id
        '                                r.Attributes(0) = Currtext.Attributes(0)
        '                                r.Attributes(1) = Currtext.Attributes(1)
        '                                Me.Result.Results.Add(r)
        '                            End If
        '                        End If
        '                        geo(ct).stato = 1

        '                        geo(ct).Seq2 = Currtext.DataText

        '                        del(ct).BeginInvoke(Nothing, Nothing)

        '                        'geo(ct).t = New Threading.Thread(AddressOf geo(ct).Check)
        '                        'geo(ct).t.Priority = Threading.ThreadPriority.Highest
        '                        'geo(ct).t.IsBackground = False
        '                        'geo(ct).t.Start()

        '                        trovatolibero = True
        '                        Exit For
        '                    End If
        '                    'Threading.Thread.Sleep(1)
        '                Next

        '            Loop Until trovatolibero



        '            '---------------------------------



        '            '' le la differenza è mi nore di quella impostasta aggiunggi l'elemento hai risulati
        '            'If r.PercDiff <= Me.PercMaxDiff Then
        '            '    r.Id = Currtext.Id
        '            '    r.Attributes(0) = Currtext.Attributes(0)
        '            '    r.Attributes(1) = Currtext.Attributes(1)
        '            '    'r.TextDate = TextTools.UIntToDate(Currtext.TextDate)
        '            '    Me.Result.Results.Add(r)
        '            'End If

        '            If Me.Filters.Count > 0 Then
        '                'se ci sono de filtri va al testo dopo
        '                i = Currtext.NextForAttributeRef(Me.Filters(0).Index.IndexType)
        '                ' se non esiste il testo succesivo vai alla key o al blocco sucessiva
        '                If i = UInteger.MaxValue Then
        '                    'verifico se sono all'ultimo blobbo della key corrente
        '                    If Me.Filters(0).Index.SortIndex(CurrPosIndex).Value.Count - 1 > CurrPosIndexBlock Then
        '                        'vado al blocco sucessimo
        '                        CurrPosIndexBlock += 1
        '                        i = Me.Filters(0).Index.SortIndex(CurrPosIndex).Value(CurrPosIndexBlock).FirstTextRef
        '                    Else
        '                        'verifico se dopo esiste una key sucessiva
        '                        If CurrPosIndex < Me.Filters(0).Index.SortIndex.Count - 1 Then
        '                            ' va alla posizine della key sucessiva al blocco 0
        '                            CurrPosIndex += 1
        '                            CurrPosIndexBlock = 0
        '                            'verifica se la key sucessiva è dentro al filtro massimo
        '                            If Me.Filters(0).Index.SortIndex(CurrPosIndex).Key <= Me.Filters(0).ValueMax Then
        '                                'posizione del testo della key sucessiva e al blocco 0
        '                                i = Me.Filters(0).Index.SortIndex(CurrPosIndex).Value(CurrPosIndexBlock).FirstTextRef
        '                            Else
        '                                i = LenFile
        '                            End If
        '                        Else
        '                            i = LenFile
        '                        End If

        '                    End If

        '                End If
        '            Else
        '                ' se la ricerca fullscan vai a quello dopo
        '                i = c.CurrBlock * c.BlockSize + j
        '            End If


        '        Else
        '            'se ID = 0 vuol dire che non esiste e va al blocco successivo
        '            i = c.BlockSize * (c.CurrBlock + 1)
        '        End If

        '        ' se ci sono i filtri a seconda del filtro vai a quello sucessivo

        '    Loop

        '    fr.Close()

        '    Const NumViewResults As Integer = 100

        '    Me.Result.Results = Me.Result.Results.OrderBy(Function(o) o.PercDiff).ToList
        '    Me.Result.CountResults = Me.Result.Results.Count
        '    If Me.Result.CountResults > NumViewResults Then
        '        Me.Result.Results.RemoveRange(NumViewResults, Me.Result.CountResults - NumViewResults)
        '    End If
        '    Me.Result.ExecTime = (Now.Ticks - t) / 10000000
        '    Me.Result.PercMaxDiff = Me.PercMaxDiff
        '    Me.Result.UseDictionary = Me.UseDictionary
        '    Me.Result.Text1 = Me.Text
        '    Me.Result.Text2 = ""

        '    Return Me.Result

        'End Function


        'Public Function Find() As SimilarResults
        '    Dim check As New CheckSimilar
        '    Dim r As SimilarResult
        '    Dim t As ULong
        '    Dim i, j As UInteger
        '    Dim Currtext As TextElement
        '    Dim LenFile As UInteger

        '    Dim IndexAttr As ArchiveIndex
        '    Dim CurrPosIndex As Integer

        '    t = Now.Ticks

        '    'assegna la percentuale massima di differenza
        '    check.PercMaxDiff = Me.PercMaxDiff
        '    ' trasporma il testi pivot in numeri
        '    check.Seq1 = New TextTools(Me.text, Me.TI).TextToNumberDic

        '    Dim fr As New IO.BinaryReader(New IO.FileStream(Folder & TI.ArchiveFile, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read))
        '    LenFile = fr.BaseStream.Length

        '    ' inizilizza l'oggetto cache **** definire la quantità di memoria da usare per una ricerca
        '    Dim c As New CacheDataFile(TI.BlockSize, 30, fr, LenFile)

        '    ' gestione filtri
        '    Me.Filters = Me.Filters.OrderBy(Function(o) o.NumRecCalc)
        '    If Me.FilterAttr Then
        '        IndexAttr = New ArchiveIndex(TI.ArchiveData & TI.IndexFileAttr)
        '        IndexAttr.SortedIndex()
        '        CurrPosIndex = IndexAttr.findkey(Me.FilterAttrMin)
        '        i = IndexAttr.SortIndex(CurrPosIndex).Value.FirstTextRef
        '    Else
        '        i = 0
        '    End If

        '    'cicla della lettura del file
        '    Do Until i >= LenFile

        '        ' prende i dati usando la cache
        '        c.GetData(i, DataTemp)
        '        'calcola offset del blocco
        '        j = i Mod c.BlockSize
        '        ' legge il testo
        '        Currtext = New TextElement(DataTemp, j)
        '        If Currtext.Id <> UInt32.MaxValue Then

        '            'imposta la sequenza da verificare
        '            check.Seq2 = Currtext.DataText
        '            'confronto pivot con testo
        '            r = check.Check()

        '            ' le la differenza è mi nore di quella impostasta aggiunggi l'elemento hai risulati
        '            If r.PercDiff1 < Me.PercMaxDiff Then
        '                r.Id = Currtext.Id
        '                r.TextAttribute = Currtext.TextAttribute
        '                r.TextDate = New Date(1, 1, 1).AddDays(Currtext.TextDate)
        '                Me.Result.Results.Add(r)
        '            End If

        '            If Me.FilterAttr Then
        '                'se ci sono de filtri va al testo dopo
        '                i = Currtext.NextForAttributeRef
        '                If i = UInteger.MaxValue Then
        '                    If CurrPosIndex < IndexAttr.SortIndex.Count - 1 Then
        '                        CurrPosIndex += 1
        '                        If IndexAttr.SortIndex(CurrPosIndex).Key <= Me.FilterAttrMax Then
        '                            i = IndexAttr.SortIndex(CurrPosIndex).Value.FirstTextRef
        '                        Else
        '                            i = LenFile
        '                        End If
        '                    Else
        '                        i = LenFile
        '                    End If
        '                End If
        '            Else
        '                ' se la ricerca fullscan vai a quello dopo
        '                i = c.CurrBlock * c.BlockSize + j
        '            End If

        '        Else
        '            'se ID = 0 vuol dire che non esiste e va al blocco successivo
        '            i = c.BlockSize * (c.CurrBlock + 1)
        '        End If

        '        ' se ci sono i filtri a seconda del filtro vai a quello sucessivo

        '    Loop

        '    fr.Close()

        '    'Me.Result.ExecTime = (Now.Ticks - t) / 10000000
        '    Me.Result.Results = Me.Result.Results.OrderByDescending(Function(o) o.PercDiff1).ToList
        '    Me.Result.ExecTime = (Now.Ticks - t) / 10000000
        '    Me.Result.Text1 = Me.text
        '    Me.Result.Text2 = ""

        '    Return Me.Result

        'End Function

    End Class

    Public Class CheckSimilar

        Public Property Seq1 As UInteger()
        Public Property Seq2 As UInteger()
        Public Property RankMin() As Integer
        Public Property Result As MatchResult

        Private Property AD As ArchiveData
        Private WordCount As UInt32
        Private WordList() As DictionaryElement
        Private WordBaseCount As UInt32
        Private WordBaseList() As DictionaryElement

        'Public AutoPercMaxDiff As Boolean

        'Public t As Threading.Thread
        'Public stato As Integer = 0

        'Public Function Check_old() As SimilarResult
        '    Dim diff, ult_par_trovata, par_trovata, par_1, par_2 As Integer
        '    Dim fa(), fb(), ft() As Integer
        '    Dim d(,) As String
        '    Dim seq As Boolean


        '    diff = 0
        '    fa = Seq1
        '    fb = Seq2

        '    par_1 = UBound(fa)
        '    par_2 = UBound(fb)

        '    If UBound(fb) > UBound(fa) Then
        '        ft = fa
        '        fa = fb
        '        fb = ft
        '    End If

        '    If UBound(fa) = -1 Then
        '        diff = UBound(fb) + 1
        '    End If

        '    If UBound(fb) = -1 Then
        '        diff = (UBound(fa) + 1)
        '    End If

        '    If diff = 0 Then

        '        ReDim d((UBound(fa) + 1), (UBound(fb) + 1))

        '        d(0, 0) = 0

        '        For i = 1 To (UBound(fa) + 1)
        '            d(i, 0) = 1
        '        Next

        '        For j = 1 To (UBound(fb) + 1)
        '            d(0, j) = 1
        '        Next

        '        diff = 0
        '        ult_par_trovata = 0
        '        For i = 1 To (UBound(fa))
        '            seq = False
        '            par_trovata = 0
        '            For j = 1 To (UBound(fb))
        '                If fa(i - 1) = fb(j - 1) Then
        '                    d(i, j) = 0
        '                    If d(ult_par_trovata, j - 1) = 0 Then
        '                        seq = True
        '                    End If
        '                    par_trovata = i
        '                Else
        '                    d(i, j) = 1
        '                End If
        '            Next
        '            If par_trovata <> 0 Then ult_par_trovata = par_trovata
        '            If Not seq Then
        '                diff = diff + 1
        '            End If

        '        Next

        '    End If

        '    'max = IIf(par_1 > par_2, par_1, par_2)
        '    'min = IIf(par_1 < par_2, par_1, par_2)

        '    Dim Result As New SimilarResult

        '    Result.PercDiff1 = diff / par_1 * 100
        '    Result.PercDiff2 = diff / par_2 * 100

        '    Return Result
        '    'Result.PercDiff1 = diff / par_1 * 100
        '    'Result.PercDiff2 = diff / par_2 * 100

        'End Function

        Public Sub New(ByVal AD As ArchiveData)

            Me.RankMin = Integer.MinValue
            Me.AD = AD

            WordCount = Me.AD.Dictionary.Words.Count
            WordList = Me.AD.Dictionary._WordsList
            WordBaseCount = Me.AD.Dictionary.DicBase.Words.Count
            WordBaseList = Me.AD.Dictionary.DicBase._WordsList

        End Sub



        'Private d(5000, 5000) As Integer
        'Private S1(100) As UInteger
        'Private S2(100) As UInteger




        'Public Function CheckNoDictionary() As MatchResult
        '    'TO DO
        '    'ok togliere l'inizio e fine come fosse una prossimità
        '    ' se trovato + volte fai sempre /2
        '    ' mettere una prossimita anche di 2 parole con il rank di prossimitò diviso 2/3/4?
        '    'ok mettere il dizionario
        '    'ok mettere a sistema tutte le parole
        '    'ok stop word
        '    'ok rimettere le parole di riferimento
        '    'ok dare rilevanza agli hashtag

        '    Dim molt As Integer

        '    Me.Result = New MatchResult

        '    Dim RankWord, MaxRankWord, TotRank As Integer

        '    Array.Clear(S1, 0, S1.Length)
        '    Array.Clear(S2, 0, S2.Length)
        '    Array.Copy(Me.Seq1, 0, S1, 1, Me.Seq1.Length)
        '    Array.Copy(Me.Seq2, 0, S2, 1, Me.Seq2.Length)
        '    TotRank = 0
        '    For ct1 = 1 To Me.Seq1.Length

        '        RankWord = 0
        '        For ct2 = 1 To Me.Seq2.Length
        '            molt = 100
        '            If S1(ct1) = S2(ct2) Then
        '                If RankWord <> 0 Then
        '                    molt = 80
        '                End If
        '                RankWord += Rank_word_word

        '                If S1(ct1 - 1) = S2(ct2 - 1) Then
        '                    RankWord += Rank_word_prox
        '                End If

        '                If S1(ct1 + 1) = S2(ct2 + 1) Then
        '                    RankWord += Rank_word_next
        '                End If
        '                RankWord = RankWord / 100 * molt
        '            End If

        '        Next


        '        TotRank += RankWord

        '        '50-(25/(x/50))

        '        If TotRank + ((Me.Seq1.Length - ct1) * 100) < Me.RankMin Then
        '            Exit For
        '        End If

        '    Next

        '    Result.Accuracy = TotRank

        '    Return Result

        'End Function

        'Public Function CheckWithDictionary() As MatchResult
        '    'TO DO
        '    'ok togliere l'inizio e fine come fosse una prossimità
        '    ' se trovato + volte fai sempre /2
        '    ' mettere una prossimita anche di 2 parole con il rank di prossimitò diviso 2/3/4?
        '    'ok mettere il dizionario
        '    'ok mettere a sistema tutte le parole
        '    'ok stop word
        '    'ok rimettere le parole di riferimento
        '    'ok dare rilevanza agli hashtag
        '    'opzione per disabilitare la porssimità degli hashtag


        '    'Dim molt As Integer
        '    Dim r As Integer

        '    Me.Result = New MatchResult

        '    Dim WeigthWord, RankWord, TotRankWord, MaxRankWord, DiffRankWord, TotRank As Integer

        '    Array.Clear(S1, 0, S1.Length)
        '    Array.Clear(S2, 0, S2.Length)
        '    Array.Copy(Me.Seq1, 0, S1, 1, Me.Seq1.Length)
        '    Array.Copy(Me.Seq2, 0, S2, 1, Me.Seq2.Length)

        '    'tolgo la prossimità dall'inizio e alla fine
        '    S1(0) = 0
        '    S2(0) = UInteger.MaxValue
        '    S1(Me.Seq1.Length + 1) = 0
        '    S2(Me.Seq2.Length + 1) = UInteger.MaxValue


        '    WeigthWord = 100
        '    '
        '    TotRank = 0
        '    For ct1 = 1 To Me.Seq1.Length

        '        TotRankWord = 0
        '        MaxRankWord = 0
        '        For ct2 = 1 To Me.Seq2.Length
        '            'molt = 100
        '            RankWord = 0

        '            r = CompareWords(S1(ct1), S2(ct2), True)
        '            If r > 0 Then
        '                'If RankWord <> 0 Then
        '                '    molt = 80
        '                'End If
        '                RankWord += WeigthWord * r / 100


        '                r = CompareWords(S1(ct1 - 1), S2(ct2 - 1), False)
        '                If r > 0 Then
        '                    RankWord += (WeigthWord * r / 100) * Rank_word_prox / 100
        '                End If

        '                r = CompareWords(S1(ct1 + 1), S2(ct2 + 1), False)
        '                If r > 0 Then
        '                    RankWord += (WeigthWord * r / 100) * Rank_word_prox / 100
        '                    'RankWord += Rank_word_prox / 100 * r
        '                End If

        '                'RankWord = RankWord / 100 * molt
        '            End If

        '            MaxRankWord = Math.Max(RankWord, MaxRankWord)
        '            TotRankWord += RankWord

        '        Next

        '        DiffRankWord = TotRankWord - MaxRankWord

        '        If DiffRankWord <> 0 Then
        '            TotRank += MaxRankWord + (40 - (2000 / DiffRankWord)) 'diminuire ancora
        '        Else
        '            TotRank += TotRankWord

        '        End If


        '        'controlle se il rank minimo non è più raggiungibile
        '        If TotRank + ((Me.Seq1.Length - ct1) * 100) < Me.RankMin Then
        '            Exit For
        '        End If

        '    Next

        '    Result.Accuracy = TotRank

        '    Return Result

        'End Function

        Public Function Check() As MatchResult
            'TO DO
            'ok togliere l'inizio e fine come fosse una prossimità
            'ok se trovato + volte fai sempre /2 (mettere una funzione log)
            ' mettere una prossimita anche di 2 parole con il rank di prossimitò diviso 2/3/4?
            'ok mettere il dizionario
            'ok mettere a sistema tutte le parole
            'ok stop word
            'ok rimettere le parole di riferimento
            'ok dare rilevanza agli hashtag
            'ok opzione per disabilitare la porssimità degli hashtag


            'Dim molt As Integer
            Dim r As Integer

            Me.Result = New MatchResult

            Dim WeigthWord, RankWord, TotRankWord, MaxRankWord, DiffRankWord, TotRank As Integer

            'peso di ogni parola
            WeigthWord = 100
            '
            TotRank = 0
            For ct1 = 0 To Me.Seq1.Length - 1

                TotRankWord = 0
                MaxRankWord = 0
                For ct2 = 0 To Me.Seq2.Length - 1
                    RankWord = 0

                    r = CompareWords(Me.Seq1(ct1), Me.Seq2(ct2), True)

                    If r > 0 Then

                        RankWord += WeigthWord * r / 100

                        If ct1 > 0 And ct2 > 0 Then
                            r = CompareWords(Me.Seq1(ct1 - 1), Me.Seq2(ct2 - 1), False)
                            If r > 0 Then
                                RankWord += (WeigthWord * r / 100) * AD.Rank_word_prox / 100
                            End If
                        End If

                        If ct1 < Me.Seq1.Length - 1 And ct2 < Me.Seq2.Length - 1 Then
                            r = CompareWords(Me.Seq1(ct1 + 1), Me.Seq2(ct2 + 1), False)
                            If r > 0 Then
                                RankWord += (WeigthWord * r / 100) * AD.Rank_word_prox / 100
                            End If
                        End If

                    End If

                    MaxRankWord = Math.Max(RankWord, MaxRankWord)
                    TotRankWord += RankWord

                Next

                DiffRankWord = TotRankWord - MaxRankWord

                If DiffRankWord <> 0 Then
                    TotRank += MaxRankWord + (40 - (2000 / DiffRankWord)) 'diminuire ancora
                Else
                    TotRank += TotRankWord

                End If


                'controlle se il rank minimo non è più raggiungibile
                If TotRank + ((Me.Seq1.Length - ct1) * 100) < Me.RankMin Then
                    Exit For
                End If

            Next

            Result.Accuracy = TotRank

            Return Result

        End Function

        'Public Function CompareWords(w1 As UInt32, w2 As UInt32, CheckHashtag As Boolean) As Integer
        '    Dim res = 0


        '    If w1 = w2 Then
        '        'word-word
        '        res = Rank_word_word
        '        If CheckHashtag And Me.TI.Dictionary.WordsList(w1).IsHashtag And Me.TI.Dictionary.WordsList(w2).IsHashtag Then
        '            'hash-hash
        '            res = Rank_Hashtag_hashtag
        '        End If
        '    Else
        '        Dim we = Me.TI.Dictionary.WordsList(w1)
        '        For ct As Integer = 0 To we.DerivateIds.Length - 1
        '            If w2 = we.DerivateIds(ct) Then
        '                If Me.TI.Dictionary.WordsList(w1).IsHashtag Then
        '                    'word-hashtag
        '                    res = Rank_word_hashtag
        '                Else
        '                    If Me.TI.Dictionary.WordsList(w2).IsHashtag Then
        '                        'word-hashtag
        '                        res = Rank_word_hashtag
        '                    Else
        '                        'stemming
        '                        res = Rank_stemming
        '                    End If
        '                End If
        '                Exit For
        '            End If
        '        Next

        '    End If

        '    Return res

        'End Function

        'Public Function aaa(i As UInt32) As DictionaryElement
        '    If i > wbasecount Then
        '        Return wlist(i - wbasecount - 1)
        '    Else
        '        Return wbaselist(i - 1)
        '    End If
        'End Function


        'Public Property WordsList(i As Integer) As DictionaryElement
        '    Get
        '        If i > Me.DicBase.Words.Count Then
        '            Return Me._WordsList(i - Me.DicBase.Words.Count - 1)
        '        Else
        '            Return Me.DicBase._WordsList(i - 1)
        '        End If
        '    End Get
        '    Set(value As DictionaryElement)
        '        Me._WordsList(i) = value
        '    End Set
        'End Property

        Public Function CompareWords(w1 As UInt32, w2 As UInt32, CheckHashtag As Boolean) As Integer
            Dim res = 0
            Dim w1_tmp = w1
            Dim w2_tmp = w2

            'Dim w1_el = Me.AD.Dictionary.WordsList(w1)
            'Dim w2_el = Me.AD.Dictionary.WordsList(w2)
            Dim w1_el As DictionaryElement
            Dim w2_el As DictionaryElement
            Dim we As DictionaryElement

            'OTTIMIZZAZIONE
            If w1 > WordBaseCount Then
                w1_el = WordList(w1 - WordBaseCount - 1)
            Else
                w1_el = WordBaseList(w1 - 1)
            End If
            'OTTIMIZZAZIONE
            If w2 > WordBaseCount Then
                w2_el = WordList(w2 - WordBaseCount - 1)
            Else
                w2_el = WordBaseList(w2 - 1)
            End If
            'Dim w1_el = aaa(w1)
            'Dim w2_el = aaa(w2)



            w1_tmp = w1
            w2_tmp = w2

            If w1_el.IsHashtag Then
                w1_tmp = w1_el.StemmingIds(0)
            End If

            If w2_el.IsHashtag Then
                w2_tmp = w2_el.StemmingIds(0)
            End If

            If w1_tmp = w2_tmp Then
                'word-word
                res = AD.Rank_word_word
            Else
                'Dim we = Me.AD.Dictionary.WordsList(w1_tmp)
                'OTTIMIZZAZIONE
                If w1_tmp > WordBaseCount Then
                    we = WordList(w1_tmp - WordBaseCount - 1)
                Else
                    we = WordBaseList(w1_tmp - 1)
                End If

                'Dim we = aaa(w1_tmp)
                For ct As Integer = 0 To we.StemmingIds.Length - 1
                    If w2_tmp = we.StemmingIds(ct) Then
                        'stemming
                        res = AD.Rank_stemming
                        Exit For
                    End If
                Next
            End If
            'Return res

            'se non serve non controlla gli hashtag
            If CheckHashtag And res > 0 Then
                If w1_el.IsHashtag And w2_el.IsHashtag Then
                    'hash-hash
                    res = res * AD.Rank_Hashtag_hashtag / 100
                ElseIf w2_el.IsHashtag Then
                    'word-hash
                    res = res * AD.Rank_word_hashtag / 100

                ElseIf w1_el.IsHashtag Then
                    'hash-word
                    res = res * AD.Rank_Hashtag_word / 100

                End If


            End If


            Return res

        End Function

        'Public Function CheckNoDictionary() As MatchResult
        '    Dim diff, ult_par_trovata, par_trovata, par_1, par_2 As Integer
        '    Dim fa(), fb() As UInteger
        '    Dim seq As Boolean


        '    Me.Result = New MatchResult

        '    fa = Me.Seq1
        '    fb = Me.Seq2

        '    diff = 0
        '    par_1 = fa.Length
        '    par_2 = fb.Length

        '    'Dim ft() as integer
        '    'If fb.Length > fa.Length Then
        '    '    ft = fa
        '    '    fa = fb
        '    '    fb = ft
        '    'End If

        '    If fa.Length = 0 Then
        '        diff = fb.Length * 100
        '    End If

        '    If fb.Length = 0 Then
        '        diff = fa.Length * 100
        '    End If

        '    If diff = 0 Then

        '        'ReDim d(fa.Length, fb.Length)

        '        d(0, 0) = 0

        '        'For i = 1 To fa.Length
        '        '    d(i, 0) = 1
        '        'Next

        '        For j = 1 To fb.Length
        '            d(0, j) = 1
        '        Next

        '        diff = 0
        '        ult_par_trovata = 0
        '        For i = 1 To fa.Length

        '            d(i, 0) = 1

        '            seq = False
        '            par_trovata = 0

        '            For j = 1 To fb.Length
        '                If fa(i - 1) = fb(j - 1) Then
        '                    d(i, j) = 0
        '                    If d(ult_par_trovata, j - 1) = 0 Then
        '                        seq = True
        '                    End If
        '                    par_trovata = i
        '                Else
        '                    d(i, j) = 1
        '                End If
        '            Next

        '            If par_trovata <> 0 Then ult_par_trovata = par_trovata
        '            If Not seq Then
        '                diff += +100
        '            End If
        '            If diff > NumMaxDiff Then
        '                Exit For
        '            End If

        '        Next
        '    End If

        '    'max = IIf(par_1 > par_2, par_1, par_2)
        '    'min = IIf(par_1 < par_2, par_1, par_2)

        '    Result.PercDiff = (diff / 100) / par_1 * 100
        '    'Result.PercDiff2 = (diff / 100) / par_2 * 100

        '    Return Result

        'End Function

        'Public Function CheckWithDictionary() As MatchResult
        '    'Dim aaa As UInteger = 0
        '    Dim ult_par_trovata, par_trovata, par_1, par_2 As Integer
        '    Dim diff, trovato_err, min_trovato_err As Integer
        '    Dim fa(), fb() As UInteger
        '    Dim seq As Boolean
        '    Dim Result As New MatchResult

        '    fa = Me.Seq1
        '    fb = Me.Seq2


        '    diff = 0
        '    par_1 = fa.Length
        '    par_2 = fb.Length

        '    If fa.Length = 0 Then
        '        diff = fb.Length * 100
        '    End If

        '    If fb.Length = 0 Then
        '        diff = fa.Length * 100
        '    End If

        '    If diff = 0 Then

        '        'ReDim d(fa.Length, fb.Length)

        '        d(0, 0) = 0

        '        'For i = 1 To fa.Length
        '        '    d(i, 0) = 100
        '        'Next

        '        For j = 1 To fb.Length
        '            d(0, j) = 100
        '        Next

        '        diff = 0
        '        ult_par_trovata = 0
        '        For i = 1 To fa.Length
        '            d(i, 0) = 1
        '            seq = False
        '            par_trovata = 0
        '            min_trovato_err = 100
        '            For j = 1 To fb.Length

        '                trovato_err = 100
        '                If fa(i - 1) = fb(j - 1) Then
        '                    trovato_err = 0
        '                Else
        '                    'cerca nel diz
        '                    'trovato_err = 0.5
        '                    For ct As Integer = 0 To Me.TI.Dictionary.Words(fb(j - 1)).DerivateIds.Length - 1
        '                        If fa(i - 1) = Me.TI.Dictionary.Words(fb(j - 1)).DerivateIds(ct) Then
        '                            trovato_err = 10
        '                            Exit For
        '                        End If
        '                    Next

        '                End If

        '                ' soglia del errore trovato per essere considerato buono
        '                d(i, j) = trovato_err
        '                If trovato_err < 100 Then
        '                    'd(i, j) = 0

        '                    'se è in sequenza, cioè quello precedente è buono aggiungi l'eventuale erore precedente
        '                    If d(ult_par_trovata, j - 1) < 100 Then
        '                        trovato_err += d(ult_par_trovata, j - 1)
        '                        seq = True
        '                        If trovato_err < min_trovato_err Then min_trovato_err = trovato_err
        '                    End If
        '                    par_trovata = i
        '                Else
        '                    'd(i, j) = 1
        '                End If
        '            Next
        '            If par_trovata <> 0 Then ult_par_trovata = par_trovata
        '            If Not seq Then
        '                diff += +100
        '            Else
        '                diff += min_trovato_err
        '            End If
        '            If diff > (NumMaxDiff) Then
        '                Exit For
        '            End If

        '        Next
        '    End If

        '    'max = IIf(par_1 > par_2, par_1, par_2)
        '    'min = IIf(par_1 < par_2, par_1, par_2)

        '    Result.Rank = (diff / 100) / par_1 * 100
        '    'Result.PercDiff2 = (diff / 100) / par_2 * 100

        '    Return Result

        'End Function


    End Class

    Public Class TextTools

        Public Property Text As String

        Private Property AD As ArchiveData

        Public Sub New(ByVal t As String, ByVal TextInit As ArchiveData)

            Me.Text = t
            Me.AD = TextInit

        End Sub
        Public Function TextToNumber() As UInteger()
            Dim Words() As String
            Dim n() As UInteger
            Dim Ctn As Integer = 0

            Words = TextToWord()

            ReDim n((Words.Length) - 1)

            For ct As Integer = 0 To Words.Length - 1

                If Not AD.Stopword.Words.ContainsKey(Words(ct)) Then

                    n(Ctn) = Me.AD.Dictionary.AddWord(Words(ct))
                    Ctn += 1

                End If

            Next

            ReDim Preserve n((Ctn) - 1)

            Return n

        End Function
        Public Function TextToWord() As String()

            Return TextToWord(Me.Text)

        End Function

        Public Shared Function TextToWord(t As String) As String()

            Return TextToWord(t, 3)

        End Function
        Public Shared Function TextToWord(t As String, MinLength As Integer) As String()
            Dim s As String

            '[^a-zA-Z0-9#]
            s = MyApp.RemoveDiacritics(t)

            s = s.Replace(vbCrLf, "_")

            s = Regex.Replace(s, "((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)", "_")

            s = Regex.Replace(s, "[^a-z\p{L}A-Z\p{L}0-9#]{1,2}", "_")


            's.Split("", StringSplitOptions.RemoveEmptyEntries)

            'Return LCase(s).Split({"_"}, StringSplitOptions.RemoveEmptyEntries).Where(Function(o) o.Length > 2).ToArray

            Return LCase(s).Split({"_"}, StringSplitOptions.RemoveEmptyEntries).Where(Function(o) o.Length >= MinLength).ToArray

        End Function

        'Public Function TextToWord() As String()
        '    Dim s As String

        '    '[^a-zA-Z0-9#]

        '    s = Replace(Me.Text, vbCrLf, "_")

        '    s = Regex.Replace(s, "\W", "_")

        '    s = Regex.Replace(s, "_{2,1000}", "_")

        '    s = s.Trim(New Char() {"_", " "})

        '    's.Split("", StringSplitOptions.RemoveEmptyEntries)

        '    Return LCase(s).Split({"_"}, StringSplitOptions.RemoveEmptyEntries)

        'End Function
        'Public Function TextToBytes() As Byte()

        '    Dim DataInt32() As UInteger = Me.TextToNumberDic()
        '    Dim DataByte() As Byte

        '    ReDim DataByte((DataInt32.Length * 4) - 1)

        '    'Array.Copy(DataInt32, 0, DataByte, 0, DataInt32.Length * 4)
        '    Buffer.BlockCopy(DataInt32, 0, DataByte, 0, DataInt32.Length * 4)

        '    Return DataByte

        'End Function

    End Class

    Public Class Util



        'Public Shared Function DateToUInt(ByVal d As Date) As UInteger


        '    Return CUInt(d.Subtract(New Date(1, 1, 1)).TotalDays)

        'End Function
        'Public Shared Function UIntToDate(ByVal n As UInteger) As Date

        '    Return New Date(1, 1, 1).AddDays(n)

        'End Function

    End Class

    <Serializable()>
    Public Class FindResult

        Public Property Matches As New List(Of MatchResult)
        Public Property ExecTime As Double
        Public Property CountResults As Integer
        Public Property PercMaxDiff As Double
        Public Property UseDictionary As Boolean
        Public Property Text1 As String
        Public Property Text2 As String

        Public Property WordCluster1 As New Dictionary(Of UInt32, Integer)
        Public Property HashTagCluster1 As New Dictionary(Of UInt32, Integer)
        Public Property HashTagCluster2 As New Dictionary(Of String, Integer)
        Public Property HashTagCluster3 As New Dictionary(Of String, Integer)

    End Class

    <Serializable()>
    Public Class MatchResult

        Public Property Accuracy As Integer

        Public Property Id As Integer

        <System.Xml.Serialization.XmlIgnore()>
        Public Property Attributes As UInteger()

        Public ReadOnly Property Attribute0() As UInteger
            Get
                Return Attributes(0)
            End Get
        End Property

        Public ReadOnly Property Attribute1() As UInteger
            Get
                Return Attributes(1)
            End Get
        End Property

        'Public Property Seq As UInteger()

        Public Sub New()

            'ReDim Me.Attributes(1)

        End Sub


        '<System.Xml.Serialization.XmlAttribute()> Public aaa As Integer
        '<System.Xml.Serialization.XmlElement("pippo")> Public bbb As Integer

        'Dim _TextAttribute As Integer
        'Public Property TextAttribute As Integer
        '    Get
        '        Return _TextAttribute
        '    End Get
        '    Set(ByVal value As Integer)
        '        _TextAttribute = value
        '    End Set
        'End Property
        'Dim _TextDate As Date
        'Public Property TextDate As Date
        '    Get
        '        Return _TextDate
        '    End Get
        '    Set(ByVal value As Date)
        '        _TextDate = value
        '    End Set
        'End Property




    End Class
End Namespace
